<?php namespace App\Http\Controllers\Api;

use App\Exceptions\SecurityException;
use App\Exceptions\SignUpException;
use App\Exceptions\InvestorAuthException;
use App\Exceptions\UserInfoAuthException;
use App\Exceptions\NotFoundException;
use App\Http\Requests;
use App\Http\Requests\CheckVerifyCodeForPhoneToAuthSession;
use App\Http\Requests\SignUpRequest;
use App\Http\Requests\GetVerifyCodeByEmailRequest;
use App\Http\Requests\GetVerifyCodeByPhoneRequest;
use App\Http\Requests\ResetPasswordByPhone;
use App\Http\Requests\ResetPasswordByEmail;
use App\Services\SendSms;
use App\Services\UserManager;
use App\Services\Tools;
use App\User;
use App\Investor;
use App\UserInfo;
use App\ProjectTeam;
use App\UserTeams;
use App\VerifyCodeByEmail;
use App\VerifyCodeByPhone;
use Illuminate\Contracts\Auth\Guard;
use Illuminate\Mail\Message;
use Request;
use Mail;
use App;

use App\Project;
use App\Exceptions\ProjectAuthException;



class AuthController extends ApiController
{

    /**
     * @param GetVerifyCodeByPhoneRequest $request
     * @param $phone
     * @return mixed
     * @throws SecurityException
     */
    public function getVerifyCodeByPhone(GetVerifyCodeByPhoneRequest $request){
        $phone = $request -> get('phone');

        $result = VerifyCodeByPhone::wherePhone($phone)->orderBy('created_at','desc')->first();

        if($result && 60 + $result->created_at->timestamp > time())
            throw new SecurityException(SecurityException::Wait60Seconds);

        VerifyCodeByPhone::wherePhone($phone)->delete();

        $VerifyCodeByPhone = new VerifyCodeByPhone();
        $VerifyCodeByPhone -> phone = $phone;
        $VerifyCodeByPhone -> verify_code = sprintf("%04d", rand(0, 9999));
        $VerifyCodeByPhone -> ip = Request::ip();
        $VerifyCodeByPhone -> ensure_session = '';

        $sendSms = new SendSms();
        $sendSms->sendSms($phone,$VerifyCodeByPhone->verify_code);

        $VerifyCodeByPhone->save();

        return $this->buildResponse(trans('api.auth.get_verification_code.success'));
    }

    /**
     * 用户注册时获取验证码
     * @param GetVerifyCodeByPhoneRequest $request
     * @return \Illuminate\View\View|\Symfony\Component\HttpFoundation\Response
     * @throws SecurityException
     * @throws SignUpException
     */
    public function getVerifyCodeByPhoneForSignUp(GetVerifyCodeByPhoneRequest $request)
    {
        $phone = $request->get('phone');

        if (User::wherePhone($phone)->exists())
            throw new SignUpException(SignUpException::PhoneExists);

        $latest = VerifyCodeByPhone::wherePhone($phone)->orderBy('created_at', 'desc')->first();

        if ($latest && $latest->created_at->timestamp + 60 > time())
            throw new SecurityException(SecurityException::Wait60Seconds);

        VerifyCodeByPhone::wherePhone($phone)->delete();

        $verifyCodeByPhone                    = new VerifyCodeByPhone();
        $verifyCodeByPhone->phone             = $phone;
        $verifyCodeByPhone->verify_code       = sprintf("%04d", rand(0, 9999));
        $verifyCodeByPhone->ip                = Request::ip();
        $verifyCodeByPhone->save();

        (new SendSms())->sendSms($phone, $verifyCodeByPhone->verify_code);

        return $this->buildResponse(trans('api.auth.get_verification_code.success'));
    }

    /**
     * 通过邮箱获取验证码
     * @param GetVerifyCodeByEmailRequest $request
     * @return \Illuminate\View\View|\Symfony\Component\HttpFoundation\Response
     * @throws SecurityException
     */
    public function getVerifyCodeByEmail(GetVerifyCodeByEmailRequest $request)
    {
        $email = $request ->get('email');
        $result = VerifyCodeByEmail::whereEmail($email)->orderBy('created_at','desc')->first();

        if($result && $result->created_at->timestamp + 60 > time())
            throw new SecurityException(SecurityException::Wait60Seconds);

        VerifyCodeByEmail::whereEmail($email)->delete();

        $verifyCodeByEmail                 = new VerifyCodeByEmail();
        $verifyCodeByEmail->email          = $email;
        $verifyCodeByEmail->verify_code    = sprintf("%04d",rand(0,9999));
        $verifyCodeByEmail->ip             = Request::ip();
        $verifyCodeByEmail->ensure_session = '';

        Mail::raw($verifyCodeByEmail->verify_code,function(Message $message) use ($email){
            $message->from('jollyzhilin@163.com','旁观者创投');
            $message->to($email)->subject('注册旁观者创投验证码');
        });

        $verifyCodeByEmail->save();

        return $this->buildResponse(trans('api.auth.getverifycode.success'));
    }

    /**
     * 验证验证码是否正确
     * @param CheckVerifyCodeForPhoneToAuthSession $request
     * @return \Illuminate\View\View|\Symfony\Component\HttpFoundation\Response
     * @throws SecurityException
     * @throws \Exception
     */
    public function checkVerifyCodeForPhoneToAuthorizeSession(CheckVerifyCodeForPhoneToAuthSession $request){
        $phone             = $request->get('phone');
        $verify_code       = $request->get('verify_code');

        /** @var VerifyCodeByPhone $verifyCodeByPhone */
        $verifyCodeByPhone = VerifyCodeByPhone::wherePhone($phone)->whereVerifyCode($verify_code)->first();
        if(!$verifyCodeByPhone || $verifyCodeByPhone->created_at->timestamp + 60 *15 < time()){
            if($verifyCodeByPhone)$verifyCodeByPhone->delete();
            throw new SecurityException(SecurityException::VerifyCodeNotMatch);
        }

        $verifyCodeByPhone->ensure_session = \Session::getId();
        $verifyCodeByPhone->save();

        return $this->buildResponse(trans('api.auth.authorize_session.success'));
    }

    /**
     * 用户注册
     * @param SignUpRequest $request
     * @return \Illuminate\View\View|\Symfony\Component\HttpFoundation\Response
     * @throws SecurityException
     * @throws SignUpException
     * @throws \Exception
     */
    public function SignUp(SignUpRequest $request){
        $username                   = $request->get('username');
        $email                      = $request->get('email');
        $phone                      = $request->get('phone');
        $password                   = $request->get('password');
        $role                       = $request->get('role');
        $verifyCodeForPhone         = $request->get('verify_code_for_phone');
        $verifyCodeForEmail         = $request->get('verify_code_for_email');

        if($username){
            throw new SecurityException(SecurityException::VerifyCodeNotMatch);
        }

        /** @var VerifyCodeByEmail $verifyCodeByEmail */
        if($email){
            $verifyCodeByEmail = VerifyCodeByEmail::whereEmail($email)->whereVerifyCode($verifyCodeForEmail)->first();
            if(!$verifyCodeByEmail || $verifyCodeByEmail->created_at->timestamp + 60 * 15 < time())
                throw new SecurityException(SecurityException::VerifyCodeNotMatch);
            $verifyCodeByEmail -> delete();
        }

        /** @var VerifyCodeByPhone $verifyCodeByPhone */
        if($phone){
            $verifyCodeByPhone = VerifyCodeByPhone::wherePhone($phone)->whereVerifyCode($verifyCodeForPhone)->first();
            if(!$verifyCodeByPhone || $verifyCodeByPhone->created_at->timestamp + 60 * 15 < time()){
                throw new SecurityException(SecurityException::VerifyCodeNotMatch);
            }
            $verifyCodeByPhone -> delete();
        }

        $user = App\Services\UserManager::signUp($username,$email,$phone,$password,$role);
        $user ->save();

        return $this->buildResponse(trans('注册成功！'),$user);
    }

    public function SignIn(Requests\SignInRequest $request){
        $loginId  = $request->get('login_id');
        $username = $request->get('username');
        $email    = $request->get('email');
        $phone    = $request->get('phone');
        $password = $request->get('password');
        $remember = $request->get('remember');

        if($phone){
            $user = UserManager::signInByPhone($phone,$password,$remember);
        }elseif($email){
            $user = UserManager::signInByEmail($email,$password,$remember);
        }elseif($username){
            $user = UserManager::signInByUsername($username,$password,$remember);
        }else{
            if(Tools::isEmail($loginId))
                $user = UserManager::signInByEmail($loginId,$password,$remember);
            else if(Tools::isPhone($loginId))
                $user = UserManager::signInByPhone($loginId,$password,$remember);
            else
                $user = UserManager::signInByUsername($loginId,$password,$remember);
        }

        return $this->buildResponse(trans('登录成功！'),$user);
    }

    public function SignOut(Guard $guard){
        $guard->logout();
        return $this->buildResponse(trans('退出成功！'));
    }

    public function ResetPasswordByPhone(ResetPasswordByPhone $request){
        $phone       = $request->get('phone');
        $verify_code = $request->get('verify_code');
        $password    = $request->get('password');

        /** @var User $user */
        $user = User::wherePhone($phone)->first();
        if(!$user)
            throw new NotFoundException(NotFoundException::UserNotFound);

        $verifyCodeByPhone = VerifyCodeByPhone::wherePhone($phone)->whereVerifyCode($verify_code)->first();
        if(!$verifyCodeByPhone || $verifyCodeByPhone->created_at->timestamp + 60 * 15 <time())
            throw new SecurityException(SecurityException::VerifyCodeNotMatch);

        $verifyCodeByPhone->delete();

        $user->password = bcrypt($password);
        $user->save();
        return $this->buildResponse(trans('api.auth.reset_password_by_phone.success'),$user);
    }


    /**
     * @param ResetPasswordByEmail $request
     */
    public function ResetPasswordByEmail(ResetPasswordByEmail $request){
        $email       = $request->get('email');          //邮箱
        $verify_code = $request->get('verify_code');    //验证码
        $password    = $request->get('password');       //密码

        //判断 邮箱是否存在
        $user = User::whereEmail($email)->first();
        if(!$user) throw new NotFoundException(NotFoundException::UserNotFound);

        //查找出邮箱跟验证码的数据，并且判断是否存在与是否有效
        $verifyCodeByEmail = VerifyCodeByEmail::whereEmail($email)->whereVerifyCode($verify_code)->first();
        if(!$verifyCodeByEmail || $verifyCodeByEmail->created_at->timestamp + 60 * 15 <time()){
            throw new SecurityException(SecurityException::VerifyCodeNotMatch);
        }
        //删除当前数据
        $verifyCodeByEmail->delete();

        //修改密码
        $user->password = bcrypt($password);
        $user->save();

        //return 返回数据
        return $this->buildResponse(trans('api.auth.reset_password_by_email.success'),$user);
    }

    /**
     * @param  Guard $guard                         投资人信息认证申请
     * @param int $auth                             表示提交认证申请
     * @return \Illuminate\View\View|\Symfony\Component\HttpFoundation\Response
     * @throws InvestorAuthException
     */
    public function InvestorAuth(Guard $guard , $auth=1 )
    {
        $UserId = $guard->user()->id;
        //判断是否存在该条信息
        if(!Investor::whereUserId($UserId)->exists())
            throw new InvestorAuthException(InvestorAuthException::NoInvestorId);

        //判断该信息是否认证  认证out or over 都不行
        if(Investor::whereUserId($UserId)->whereStatus(1)->first())
            throw new InvestorAuthException(InvestorAuthException::InvestorAuthIsPasses);

        if($Investor = Investor::whereUserId($UserId)->whereStatus(0)->first())
        {
            $Investor->status = $auth;
            $Investor->save();
            return $this->buildResponse(trans('api.InvestorAuth_apply.success'));
        }
    }



    /**
     * 验证项目
     *
     * @param Guard $guard
     * @param $project_id
     * @param int $auth
     * @return \Illuminate\View\View|\Symfony\Component\HttpFoundation\Response
     * @throws ProjectAuthException
     * @throws SecurityException
     */
    public function ProjectAuth(Guard $guard , $project_id, $auth=1)
    {
        if($guard->guest())
            throw new SecurityException(SecurityException::LoginFirst);

        /** @var User  $currentUser */
        $currentUser = $guard->user();
        $userId = $currentUser->id;
        if(!$currentUser)
            throw new SecurityException(SecurityException::NoPermission);
        /** 项目在认证中 */
        if(Project::whereId($project_id)->whereUserId($userId)->whereProjectAuth(1)->exists())
            throw new ProjectAuthException(ProjectAuthException::ProjectIsCertification);

        /** 判断该项目是否属于该用户 */
        if(!Project::whereId($project_id)->whereUserId($userId))
            throw new ProjectAuthException(ProjectAuthException::ProjectNotHasUser);

        /** 通过project_table 查出对应信息 */
        $this->CheckProject($project_id);

        /** 检查 融资需求模块 */
        $this->CheckInvestNeed($project_id);

        $Project = Project::find($project_id);
        $ProjectMilestone = new App\ProjectMilestone();
        /** 检查里程碑模块 */
        if( $ProjectMilestone->whereProjectId($project_id)->count() < 0)
            throw new ProjectAuthException(ProjectAuthException::NoProjectMilestone);

        /** 检查项目团队信息 */
        $teamId = ProjectTeam::whereProjectId($project_id)->pluck('team_id');

        if(ProjectTeam::whereProjectId($project_id)->count() < 0)
            throw new ProjectAuthException(ProjectAuthException::NoUserTeams);

        if(! UserTeams::whereId($teamId)->pluck('photo_id'))
            throw new ProjectAuthException(ProjectAuthException::NoUserTeamsLogo);

        /** 提交审核申请 */
        $Project->project_auth = $auth;
        if($Project->save())
            return $this->buildResponse(trans('api.ProjectAuth_apply.success'));
    }

    /**
     * @param $project_id               检查项目信息是否完善
     * @throws ProjectAuthException
     */
    private function CheckProject($project_id)
    {
        if(!Project::whereId($project_id)->pluck('project_name'))
            throw new ProjectAuthException(ProjectAuthException::NoProjectName);

        if(!Project::whereId($project_id)->pluck('company_name'))
            throw new ProjectAuthException(ProjectAuthException::NoCompanyName);

        if(!Project::whereId($project_id)->pluck('field_id'))
            throw new ProjectAuthException(ProjectAuthException::NoFieldId);

        if(!Project::whereId($project_id)->pluck('phase_id'))
            throw new ProjectAuthException(ProjectAuthException::NoPhaseId);

        if(!Project::whereId($project_id)->pluck('project_tags'))
            throw new ProjectAuthException(ProjectAuthException::NoProjectTags);

        if(!Project::whereId($project_id)->pluck('img_projectlogo_id'))
            throw new ProjectAuthException(ProjectAuthException::NoProjectLogo);

        if(!Project::whereId($project_id)->pluck('province') || !Project::whereId($project_id)->pluck('city'))
            throw new ProjectAuthException(ProjectAuthException::NoLocation);

        if(!Project::whereId($project_id)->pluck('url_id'))
            throw new ProjectAuthException(ProjectAuthException::NoUrl);

        if(!Project::whereId($project_id)->pluck('create_time'))
            throw new ProjectAuthException(ProjectAuthException::NoCreateTime);

    }

    /**
     * @param $project_id           检查融资需求模块
     * @throws ProjectAuthException
     */
    public function CheckInvestNeed($project_id)
    {
        if(!Project::whereId($project_id)->pluck('invet'))
            throw new ProjectAuthException(ProjectAuthException::NoInvet);

        if(!Project::whereId($project_id)->pluck('sell_stock'))
            throw new ProjectAuthException(ProjectAuthException::NoSellStock);

        if(!Project::whereId($project_id)->pluck('min_money'))
            throw new ProjectAuthException(ProjectAuthException::NoMinMoney);

        if(!Project::whereId($project_id)->pluck('invest_num'))
            throw new ProjectAuthException(ProjectAuthException::NoInvestNum);

        if(!Project::whereId($project_id)->pluck('is_finance'))
            throw new ProjectAuthException(ProjectAuthException::NotIsFinance);
    }
}


